using B.S.Medical.Api.Read.Application.Command.Payment;
using B.S.Medical.Domain.Medical;
using B.S.Medical.Domain.Payment;
using B.S.Medical.ErrorCode;
using B.S.Medical.Infrastructure.Interface;
using MediatR;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace B.S.Medical.Api.Read.Application.Handler.Payment
{
    /// <summary>
    /// 提交退款处理器
    /// </summary>
    public class SubmitRefundHandler : IRequestHandler<SubmitRefundCommand, ApiResult<RefundResultDto>>
    {
        private readonly IBaseRepository<PaymentRecordModel> _paymentRecordRepository;
        private readonly IBaseRepository<PatientBalance> _patientBalanceRepository;
        private readonly ILogger<SubmitRefundHandler> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        public SubmitRefundHandler(
            IBaseRepository<PaymentRecordModel> paymentRecordRepository,
            IBaseRepository<PatientBalance> patientBalanceRepository,
            ILogger<SubmitRefundHandler> logger)
        {
            _paymentRecordRepository = paymentRecordRepository;
            _patientBalanceRepository = patientBalanceRepository;
            _logger = logger;
        }

        /// <summary>
        /// 处理提交退款命令
        /// </summary>
        public async Task<ApiResult<RefundResultDto>> Handle(SubmitRefundCommand request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation($"开始处理退款请求，PaymentId: {request.PaymentId}, OrderNo: {request.OrderNo}, RefundAmount: {request.RefundAmount}");

                // 查询支付记录
                PaymentRecordModel paymentRecord = null;
                
                if (request.PaymentId > 0)
                {
                    paymentRecord = _paymentRecordRepository.GetAll()
                        .Where(p => p.Id == request.PaymentId && !p.IsDeleted && p.IsPaid && p.RefundStatus != "已退款")
                        .FirstOrDefault();
                }
                else if (!string.IsNullOrEmpty(request.OrderNo))
                {
                    paymentRecord = _paymentRecordRepository.GetAll()
                        .Where(p => p.OrderNo == request.OrderNo && !p.IsDeleted && p.IsPaid && p.RefundStatus != "已退款")
                        .FirstOrDefault();
                }

                if (paymentRecord == null)
                {
                    _logger.LogWarning($"未找到可退款的支付记录，PaymentId: {request.PaymentId}, OrderNo: {request.OrderNo}");
                    return new ApiResult<RefundResultDto>
                    {
                        Code = ApiEnum.Fail,
                        Msg = "未找到可退款的支付记录"
                    };
                }

                // 验证退款金额
                if (request.RefundAmount <= 0 || request.RefundAmount > paymentRecord.Amount)
                {
                    _logger.LogWarning($"退款金额无效，RefundAmount: {request.RefundAmount}, PaymentAmount: {paymentRecord.Amount}");
                    return new ApiResult<RefundResultDto>
                    {
                        Code = ApiEnum.Fail,
                        Msg = "退款金额无效，必须大于0且不超过支付金额"
                    };
                }

                // 查询患者余额
                var patientBalance = _patientBalanceRepository.GetAll()
                    .Where(b => b.PatientId == paymentRecord.PatientId && !b.IsDeleted)
                    .FirstOrDefault();

                decimal oldBalance = patientBalance?.Balance ?? 0;
                decimal newBalance = oldBalance + request.RefundAmount;

                // 生成退款流水号
                string refundTradeNo = $"RF{DateTime.Now:yyyyMMddHHmmss}{new Random().Next(1000, 9999)}";
                DateTime refundTime = DateTime.Now;

                // 更新支付记录
                paymentRecord.RefundAmount = request.RefundAmount;
                paymentRecord.RefundStatus = "已退款";
                paymentRecord.RefundTradeNo = refundTradeNo;
                paymentRecord.RefundTime = refundTime;
                paymentRecord.UpdateTime = DateTime.Now;

                // 更新患者余额
                if (patientBalance != null)
                {
                    patientBalance.Balance = newBalance;
                    patientBalance.LastUpdatedTime = DateTime.Now;
                    patientBalance.Remark = $"退款：{request.RefundAmount}元，订单号：{paymentRecord.OrderNo}";
                    
                    await _patientBalanceRepository.UpdateAsync(patientBalance);
                }
                else
                {
                    // 如果没有余额记录，创建一个新的
                    patientBalance = new PatientBalance
                    {
                        PatientId = paymentRecord.PatientId,
                        Balance = request.RefundAmount,
                        LastUpdatedTime = DateTime.Now,
                        Remark = $"退款：{request.RefundAmount}元，订单号：{paymentRecord.OrderNo}"
                    };
                    
                    await _patientBalanceRepository.CreateAsync(patientBalance);
                }

                // 更新支付记录
                await _paymentRecordRepository.UpdateAsync(paymentRecord);

                _logger.LogInformation($"退款成功，PaymentId: {paymentRecord.Id}, OrderNo: {paymentRecord.OrderNo}, RefundAmount: {request.RefundAmount}, RefundTradeNo: {refundTradeNo}");

                // 构建返回结果
                var result = new RefundResultDto
                {
                    Success = true,
                    RefundAmount = request.RefundAmount,
                    CardBalance = newBalance,
                    RefundTradeNo = refundTradeNo,
                    RefundTime = refundTime
                };

                return new ApiResult<RefundResultDto>
                {
                    Code = ApiEnum.Success,
                    Msg = "退款成功",
                    Data = result
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"处理退款请求时发生错误，PaymentId: {request.PaymentId}, OrderNo: {request.OrderNo}, RefundAmount: {request.RefundAmount}");
                return new ApiResult<RefundResultDto>
                {
                    Code = ApiEnum.Error,
                    Msg = $"退款失败: {ex.Message}"
                };
            }
        }
    }
} 